#include "vsf.h"
#include "vsfjeg.h"

#define VSFJEG_DECODER_EVT_SYNC				(VSFSM_EVT_USER + 0)
#define VSFJEG_DECODER_EVT_OUT				(VSFSM_EVT_USER + 1)

static void vsfjeg_decoder_on_sync(struct vsfav_adapter_t *adapter)
{
	struct vsfjeg_decoder_t *decoder = (struct vsfjeg_decoder_t *)adapter;
	vsfsm_post_evt_pending(&decoder->sm, VSFJEG_DECODER_EVT_SYNC);
}

void vsfjeg_decoder_on_inout(struct vsfav_adapter_t *adapter, bool isin)
{
	struct vsfjeg_decoder_t *decoder = (struct vsfjeg_decoder_t *)adapter;
	if (!isin && decoder->out_pend)
	{
		decoder->out_pend = false;
		vsfsm_post_evt_pending(&decoder->sm, VSFJEG_DECODER_EVT_OUT);
	}
}

static struct vsfsm_state_t *
vsfjeg_decoder_evthandler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfjeg_decoder_t *decoder = (struct vsfjeg_decoder_t *)sm->user_data;
	struct vsf_buffer_t rxbuf, txbuf;

	switch (evt)
	{
	case VSFSM_EVT_INIT:
		decoder->out_pend = false;
		decoder->sync = 0;
		decoder->buflist[0] = decoder->buffer[0];
		decoder->buflist[1] = decoder->buffer[1];
		decoder->mbuf.mem.multibuf.size = sizeof(decoder->buffer[0]);
		decoder->mbuf.mem.multibuf.buffer_list = decoder->buflist;
		decoder->mbuf.mem.multibuf.count = dimof(decoder->buflist);
		decoder->mbuf.stream.op = &vsf_mbufstream_op;
		VSFSTREAM_INIT(&decoder->mbuf);
		VSFSTREAM_CONNECT_TX(&decoder->mbuf);
		decoder->outstream.stream = &decoder->mbuf.stream;
		decoder->adapter.out = &decoder->outstream;
		vsfav_adapter_init(&decoder->adapter, vsfjeg_decoder_on_inout,
				vsfjeg_decoder_on_sync);
		break;
	case VSFJEG_DECODER_EVT_SYNC:
		decoder->sync++;
		if (decoder->sync > 1)
			break;

		while (decoder->sync)
		{
			decoder->size = VSFSTREAM_GET_RBUF(decoder->adapter.in->stream,
					&decoder->ptr);
			while (decoder->size > 0)
			{
				rxbuf.buffer = decoder->ptr;
				rxbuf.size = decoder->size;
/*
	case VSFSM_EVT_DATAOUT:
				txbuf.size = VSFSTREAM_GET_WBUF(&decoder->mbuf, &txbuf.buffer);
				if (!txbuf.size)
				{
					decoder->out_pend = true;
					return NULL;
				}

				// TODO: convert to RGB565, set rxbuf.size to the real size
				rxbuf.size = min(rxbuf.size, txbuf.size);
				txbuf.size = rxbuf.size;
				memcpy(txbuf.buffer, 
*/
				decoder->size -= rxbuf.size;
			}
			VSFSTREAM_READ(decoder->adapter.in->stream, NULL);
			vsfsm_sem_post(&decoder->outstream.frame_sync);
			decoder->sync--;
		}
		break;
	}
	return NULL;
}

vsf_err_t vsfjeg_decoder_init(struct vsfjeg_decoder_t *decoder,
		struct vsfav_stream_t *stream)
{
	decoder->adapter.in = stream;
	decoder->sm.init_state.evt_handler = vsfjeg_decoder_evthandler;
	decoder->sm.user_data = decoder;
	return vsfsm_init(&decoder->sm);
}
